/**
 * 
 */
package com.zdy.im.tio.command;


import com.sixeco.framework.common.constants.ReflectionsScan;
import com.zdy.im.common.exception.ImException;
import com.zdy.im.core.ICommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * 版本: [1.0]
 * 功能说明: 命令执行管理器;
 * @Author 作者 : zdy
 * @CreateDate 创建时间: 2021-02-30
 */
@Component
public class CommandHandlerManager {
	/**
	 * 通用cmd处理命令
	 */
	private static  Map<Integer, Class> handlerMap = new HashMap<>();

	private static Logger logge = LoggerFactory.getLogger(CommandHandlerManager.class);

	private CommandHandlerManager(){};

	@Autowired
	private ApplicationContext applicationContext;
	
	@PostConstruct
	public void reflectionsCmdHandlerExt() {
		Set<Class<? extends CmdHandler>> classList = ReflectionsScanZDY.reflections.getSubTypesOf(CmdHandler.class);
		if(null == classList || classList.isEmpty()){
			return ;
		}
		for (Class<?> clazz : classList){
			try {
				boolean isAbstract = Modifier.isAbstract(clazz.getModifiers());
				if(isAbstract){continue;}
				/**
				 * 强制继续实现方法转换类增加到拦截器中;
				 */
				boolean isResolver = CmdHandler.class.isAssignableFrom(clazz);
				if (isResolver){
					registerCommand(clazz);
				}
//				Object cmdHandler = applicationContext.getBean(clazz);
//				CmdHandler cmd = (CmdHandler)cmdHandler;
//				this.getCommand(cmd.command().getNumber()+"");

			}catch (Exception e){
				e.printStackTrace();
			}
		}

		handlerMap.toString();
	}

	public  <T extends  CmdHandler>void registerCommand(Class<?> clazz) throws Exception{
		if(null == clazz ){
			return ;
		}
		CmdHandler cmdHandler = (CmdHandler)clazz.newInstance();
		if(cmdHandler == null || cmdHandler.command() == null) {
			return ;
		}
		//检查创建的功能协议是否有返回功能协议码,是否合理
		int cmdNumber = cmdHandler.command().getNumber();
		ICommand iCommand = Command.forNumber(cmdNumber);
		if(null == iCommand){
			throw new ImException("failed to register cmd handler, illegal cmd code:" + cmdNumber + ",use Command.addAndGet () to add in the enumerated Command class!");
		}
		Class exClass = handlerMap.get(cmdNumber);
		if(Objects.isNull(exClass))
		{
			handlerMap.put(cmdNumber,clazz);
			logge.info(" to CmdHandler object by applicationContext cmd[{}] -- Bean Class[{}]" ,cmdNumber,clazz);
		}else{
			throw new ImException("cmd code:"+cmdNumber+",-- Bean Class[1。"+exClass+" , 2."+clazz+"]has been registered, please correct!");
		}
	}
	
	public  boolean removeCommand(Command command){
		if(command == null) {
			return false;
		}
		Integer cmdValue = command.getNumber();
		if(handlerMap.get(cmdValue) != null)
		{
			 handlerMap.remove(cmdValue);
			 return true;
		}
		return false;
	}


	public  <T extends CmdHandler> T getCommand(Command command,Class<T> clazz){
		if(command == null) {
			return null;
		}
		Class<CmdHandler> cmdHandlerClass = handlerMap.get(command.getNumber());
		if(cmdHandlerClass != null && cmdHandlerClass.equals(clazz)){
			//通过名称和类名获取拦截器
			T cmdHandler = applicationContext.getBean(clazz);
			return cmdHandler;
		}

		return null;
	}
	public CmdHandler getCommand(Command command){
		return getCommand(command.getNumber());
	}
	public  CmdHandler  getCommand(String commandNo){
		if(commandNo == null || "".equals(commandNo)) {
			return null;
		}
		Integer command = Integer.parseInt(commandNo);
		return getCommand(command);
	}
	public  CmdHandler  getCommand(Integer command){

		if(null == command){
			return null;
		}

		Class<CmdHandler> cmdHandlerClass = handlerMap.get(command);
		if(cmdHandlerClass != null){
			CmdHandler cmdHandler = applicationContext.getBean(cmdHandlerClass);
			return cmdHandler;
		}

		return null;
	}
	

}
